//
//  NSObject+LGSwizzing.m
//  CustomLeakTest
//
//  Created by yunyi on 2020/4/24.
//  Copyright © 2020 yunyi. All rights reserved.
//

#import "NSObject+LGSwizzing.h"
#import <objc/runtime.h>

@implementation NSObject (LGSwizzing)
/**
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)

作用：这个方法的作用是，给类添加一个新的方法和该方法的具体实现

BOOL: 返回值，yes-------方法添加成功     no--------方法添加失败

Class cls: 将要给添加方法的类，传的类型 ［类名  class］

SEL name: 将要添加的方法名，传的类型   @selector(方法名)

IMP imp：实现这个方法的函数 ，传的类型   1，C语言写法：（IMP）方法名    2，OC的写法：class_getMethodImplementation(self,@selector(方法名：))

const char *types：表示我们要添加的方法的返回值和参数

"v@:@"：v：是添加方法无返回值    @表示是id(也就是要添加的类) ：表示添加的方法类型  @表示：参数类型


还有一点需要注意，用这个方法添加的方法是无法直接调用的，必须用performSelector：调用。

因为performSelector是运行时系统负责去找方法的，在编译时候不做任何校验；如果直接调用编译是会自动校验。

你添加方法是在运行时添加的，你在编译的时候还没有这个本类方法，所以当然不行。


*/


+ (void)swizzleSEL:(SEL)oringSEL withSEL:(SEL)swizzlingSEL {
    //1.获取到当前的Class
    Class class = [self class];
    
    //2.得到原始方法 和需要交换的方法
    Method originMethod = class_getInstanceMethod(class, oringSEL);
    Method currentMethod = class_getInstanceMethod(class, swizzlingSEL);
    
    //3.判断当前类中需要替换的的方法有没有在当前类中实现
    /**
     class_addMethod是runtime中的动态添加方法，如果能够添加成功说明本类并没有实现这个要添加的方法，如果不能添加成功说明本类实现这个方法。实现方法包括新增的方法和重写父类方法。
    */
    BOOL didAddMethod = class_addMethod(class, oringSEL, method_getImplementation(currentMethod), method_getTypeEncoding(currentMethod));
    if (didAddMethod) {
        //代表当前类中被替换的方法已经实现， 那就开始替换
        //调用了class_replaceMethod会把原来方法的IMP指向另一个方法的实现
        class_replaceMethod(class, swizzlingSEL, method_getImplementation(currentMethod), method_getTypeEncoding(currentMethod));
    } else {
        //如果没有实现 则替换方法
        method_exchangeImplementations(originMethod, currentMethod);
    }
}

- (void)willDealloc {
    __weak typeof(self) weakSelf = self;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        //在block中引用
        __strong typeof(self) strongSelf = weakSelf;
        NSLog(@"lg_WillDealloc===============%@",strongSelf);
    });
}
@end
